﻿namespace com.oakwoodsys.ConsultantCareDao
{
    // TimeZone http://technet.microsoft.com/en-us/library/hh147944.aspx
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using com.oakwoodsys.Extensions.DateTimeExtensions;
    using com.oakwoodsys.Extensions.DoubleExtensions;
    using com.oakwoodsys.Extensions.SharePointExtensions;
    using com.oakwoodsys.SharePoint;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Linq;

    using Context = ConsultantCareDataContext;

    using ReferenceObject = CalendarEvent;

    public class CalendarEventDao : BaseDao
    {
        #region Fields

        public const string ListName = "calendar";

        #endregion Fields

        #region Constructors

        public CalendarEventDao( )
            : base(ListName)
        {
            CurrentWebUrl = SPContext.Current.Web.Url;
        }

        public CalendarEventDao( string currentWebUrl )
            : base(ListName)
        {
            CurrentWebUrl = currentWebUrl;
        }

        public CalendarEventDao( string currentWebUrl, SharePointUri calendarUri )
            : base(calendarUri.RootFolderName)
        {
            CurrentWebUrl = currentWebUrl;
            CalendarUri = calendarUri;
        }

        #endregion Constructors

        #region Properties

        public SharePointUri CalendarUri
        {
            get;
            private set;
        }

        #endregion Properties

        #region Methods

        public Guid Add( ReferenceObject value )
        {
            using ( SPSite spSite = new SPSite( CurrentWebUrl ) )
            {
                using ( SPWeb spWeb = spSite.OpenWeb( ) )
                {
                    SPList spList = spWeb.Lists[ ListTitle ];
                    spWeb.AllowUnsafeUpdates = true;
                    SPListItem item = spList.Items.Add( );

                    item.SetValue<bool>( MapTo.AllDayEvent, value.AllDayEvent );
                    item.SetValue<string>( MapTo.Category, value.Category );
                    item.SetValue<string>( MapTo.Description, value.Description );
                    item.SetValue<DateTime>( MapTo.EndDate, value.EndDate );
                    item.SetValue<string>( MapTo.Location, value.Location );
                    item.SetValue<DateTime>( MapTo.StartTime, value.StartTime );
                    item.SetValue<string>( MapTo.Title, value.Title );
                    item.Update( );
                    spWeb.AllowUnsafeUpdates = false;
                    return item.UniqueId;
                }
            }
        }

        public ReferenceObject Get( Guid uniqueId )
        {
            List<ReferenceObject> l = getItems( Query.Get( Query.ByUniqueId, uniqueId ) );
            if ( l.Count > 0 )
                return l[ 0 ];
            else
                return null;
        }

        public void Remove( Guid uniqueId )
        {
            using ( SPSite spSite = new SPSite( CurrentWebUrl ) )
            {
                using ( SPWeb spWeb = spSite.OpenWeb( ) )
                {
                    SPList spList = spWeb.Lists[ ListTitle ];
                    ReferenceObject item = Get( uniqueId );
                    DateTime now = DateTime.Now;
                    if ( item != null )
                        if ( item.StartTime.Date >= now.Date )
                            spList.Items.DeleteItemById( item.Id.Value );
                }
            }
        }

        List<ReferenceObject> getItems( string query )
        {
            using ( SPSite spSite = new SPSite( CurrentWebUrl ) )
            {
                using ( SPWeb spWeb = spSite.OpenWeb( ) )
                {
                    SPList spList = spWeb.Lists[ ListTitle ];
                    SPQuery spQuery = new SPQuery
                    {
                        Query = query
                    };
                    SPListItemCollection spListItemCollection = spList.GetItems( spQuery );
                    List<ReferenceObject> l = new List<ReferenceObject>( );
                    foreach ( SPListItem item in spListItemCollection )
                    {
                        l.Add( map( item ) );
                    }
                    return l;
                }
            }
        }

        ReferenceObject map( SPListItem item )
        {
            return new ReferenceObject
            {
                AllDayEvent = item.GetValue<bool>( MapTo.AllDayEvent ),
                Category = item.GetValue<string>( MapTo.Category ),
                Description = item.GetValue<string>( MapTo.Description ),
                EndDate = item.GetValue<DateTime>( MapTo.EndDate ),
                Id = item.GetValue<int>( MapTo.ID ),
                Location = item.GetValue<string>( MapTo.Location ),
                StartTime = item.GetValue<DateTime>( MapTo.StartTime ),
                Title = item.GetValue<string>( MapTo.Title ),
                UniqueId = item.GetValue<Guid>( MapTo.UniqueId )
            };
        }

        #endregion Methods

        #region Nested Types

        public class MapTo
        {
            #region Fields

            public const string AllDayEvent = "fAllDayEvent";
            public const string Category = "Category";
            public const string Description = "Description";
            public const string EndDate = "EndDate"; //End Time
            public const string EventType = "EventType";
            public const string ID = "ID";
            public const string IsRecurring = "fRecurrence";
            public const string Location = "Location";
            public const string RecurrenceData = "RecurrenceData";
            public const string StartTime = "EventDate"; //Start Time
            public const string Title = "Title";
            public const string UniqueId = "UniqueId";

            #endregion Fields
        }

        class Query
        {
            #region Fields

            public const string All = "<OrderBy><FieldRef Name='Created' Ascending='True'/></OrderBy>";
            public const string ById = "<Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>{0}</Value></Eq></Where>";
            public const string ByTitle = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>{0}</Value></Eq></Where>";
            public const string ByUniqueId = "<Where><Eq><FieldRef Name='UniqueId' /><Value Type='Guid'>{0}</Value></Eq></Where>";

            #endregion Fields

            #region Methods

            public static string Get( string query, params object[ ] args )
            {
                return string.Format( query, args );
            }

            #endregion Methods
        }

        #endregion Nested Types
    }
}